package com.talent.core.protocol.mqtt;


import com.talent.core.protocol.mqtt.codec.TlMqttMessageCodec;
import com.talent.core.protocol.mqtt.codec.encoder.*;
import com.talent.core.protocol.mqtt.config.TlMqttConfig;
import com.talent.core.protocol.mqtt.config.TlPortConfig;
import com.talent.core.protocol.mqtt.handler.*;
import com.talent.core.protocol.mqtt.store.IMqttStore;
import com.talent.core.protocol.mqtt.store.TlMqttLocalStore;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;

/**
 * @ClassName：Server
 * @Author: hszhou
 * @Date: 2024/11/15 15:10
 * @Description: 启动类
 */
public class TlMqttServer {

    private static final  Logger logger = LoggerFactory.getLogger(TlMqttServer.class);


    NioEventLoopGroup work = new NioEventLoopGroup();
    NioEventLoopGroup boss = new NioEventLoopGroup();
    ServerBootstrap bootstrap = new ServerBootstrap();
    IMqttStore mqttStore = new TlMqttLocalStore();
    TlMqttMessageCodec mqttMessageCodec = new TlMqttMessageCodec();

    TlMqttConnectHandler mqttConnectHandler = new TlMqttConnectHandler(mqttStore);
    TlMqttPublishHandler mqttPublishHandler = new TlMqttPublishHandler(mqttStore);
    TlMqttSubScribeHandler mqttSubScribeHandler = new TlMqttSubScribeHandler(mqttStore);
    TlMqttUnSubScribeHandler mqttUnSubScribeHandler = new TlMqttUnSubScribeHandler(mqttStore);
    TlMqttHeartBeatHandler mqttHeartBeatHandler = new TlMqttHeartBeatHandler();
    TlMqttDisconnectHandler mqttDisconnectHandler = new TlMqttDisconnectHandler(mqttStore);
    TlMqttPubCompHandler mqttPubCompHandler = new TlMqttPubCompHandler(mqttStore);
    TlMqttPubAckHandler mqttPubAckHandler = new TlMqttPubAckHandler(mqttStore);
    TlMqttPubRecHandler mqttPubRecHandler = new TlMqttPubRecHandler(mqttStore);
    TlMqttPubRelHandler mqttPubRelHandler = new TlMqttPubRelHandler(mqttStore);
    TlMqttConnackEncoder mqttConnackEncoder = new TlMqttConnackEncoder();
    TlMqttHeaderBeatEncoder mqttHeaderBeatEncoder = new TlMqttHeaderBeatEncoder();
    TlMqttSubAckEncoder mqttSubAckEncoder = new TlMqttSubAckEncoder();
    TlMqttUnSubAckEncoder mqttUnSubAckEncoder = new TlMqttUnSubAckEncoder();
    TlMqttPublishEncoder mqttPublishEncoder = new TlMqttPublishEncoder();
    TlMqttPubAckEncoder mqttPubAckEncoder = new TlMqttPubAckEncoder();
    TlMqttPubRecEncoder mqttPubRecEncoder = new TlMqttPubRecEncoder();
    TlMqttPubCompEncoder mqttPubCompEncoder = new TlMqttPubCompEncoder();
    TlMqttExceptionHandler mqttExceptionHandler = new TlMqttExceptionHandler(mqttStore);
    HeartbeatEventTriggered heartbeatEventTriggered = new HeartbeatEventTriggered();

    public void start(){



        Yaml yaml = new Yaml(new Constructor(TlMqttConfig.class));
        TlMqttConfig config = yaml.load(this.getClass().getClassLoader()
                .getResourceAsStream("config.yml"));
        TlPortConfig port = config.getPort();
        int mqtt = port.getMqtt();

        try {
            bootstrap.group(boss,work)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new TlMqttChannelInitializer(
                            mqttMessageCodec,
                            mqttConnectHandler,
                            mqttPublishHandler,
                            mqttSubScribeHandler,
                            mqttUnSubScribeHandler,
                            mqttHeartBeatHandler,
                            mqttDisconnectHandler,
                            mqttPubCompHandler,
                            mqttPubAckHandler,
                            mqttPubRecHandler,
                            mqttPubRelHandler,
                            mqttConnackEncoder,
                            mqttHeaderBeatEncoder,
                            mqttSubAckEncoder,
                            mqttUnSubAckEncoder,
                            mqttPublishEncoder,
                            mqttPubAckEncoder,
                            mqttPubRecEncoder,
                            mqttPubCompEncoder,
                            mqttExceptionHandler,
                            heartbeatEventTriggered));
            ChannelFuture channelFuture = bootstrap.bind(mqtt).sync();
            logger.info("mqtt服务器启动成功");
            channelFuture.channel().closeFuture().addListener(r->{
                work.shutdownGracefully();
                boss.shutdownGracefully();
            });
        }catch (Exception e){
            e.printStackTrace();
            logger.error("出现异常");
        }
    }
    public static void main(String[] args) {
        TlMqttServer server = new TlMqttServer();
        server.start();
    }
}
